/*
 * Copyright (c) 2009-2013 EvTech Project
 * All rights reserved.
 * 
 * This file is part of Symbol Matching.
 *
 * Symbol Matching is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version.
 *
 * Symbol Matching is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Symbol Matching.  If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package fi.honkalampisaatio.reaktiopeli.game;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;

import javax.swing.Box;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.filechooser.FileFilter;

import fi.honkalampisaatio.game.game.LanguageResource;
import fi.honkalampisaatio.game.ui.ScalableCheckBox;
import fi.honkalampisaatio.game.ui.ScalableIconButton;
import fi.honkalampisaatio.game.ui.ScalableIconLabel;
import fi.honkalampisaatio.reaktiopeli.setup.SetupData;
import fi.honkalampisaatio.reaktiopeli.setup.SetupEvent;
import fi.honkalampisaatio.reaktiopeli.setup.SetupEventListener;
import fi.honkalampisaatio.reaktiopeli.setup.SetupEvent.MESSAGE;
import fi.honkalampisaatio.reaktiopeli.xml.GameDifficulty;

public class GameOptionsPanel extends JPanel implements KeyListener, ActionListener {

	private static final long serialVersionUID = -3139594083379099016L;
	private SetupEventListener listener;
	
	private ScalableIconLabel difficultyLabel;
	private ScalableIconLabel omitMistakesLabel;
	private ScalableIconLabel showScoreLabel;
	private ScalableIconLabel showTimeLabel;

	private ScalableIconButton cancelButton;
	private ScalableIconButton okButton;
	
	private JComboBox<ScalableIconLabel> difficulty;
	private ScalableCheckBox omitMistakes;
	private ScalableCheckBox showScore;
	private ScalableCheckBox showTime;
	private ScalableIconButton chooseCorrectAnswerImageButton;
	private ImagePanel correctAnswerImagePanel;
	
	private ImageAndTextComboBoxRenderer difficultyRenderer;

	private LanguageResource dictionary; 


	public GameOptionsPanel() {
		dictionary = LanguageResource.getInstance();
		this.addKeyListener(this);
		
		GridLayout  layout = new GridLayout (0,2,50,10);
		this.setLayout(layout);

		difficultyLabel = new ScalableIconLabel(dictionary.get("DIFFICULTYLABEL_TEXT"),
				"./settings/images/Vaikeustaso.png");
		difficultyLabel.setHorizontalAlignment(JLabel.CENTER);
		this.add(difficultyLabel);
		
		difficultyRenderer = new ImageAndTextComboBoxRenderer();
		difficulty = new JComboBox<ScalableIconLabel>();
		difficulty.setRenderer(difficultyRenderer);
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.ROUNDS10.toString()),
				"./settings/images/Kierrosta kuvake pieni.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.ROUNDS20.toString()),
				"./settings/images/Kierrosta kuvake pieni.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.ROUNDS30.toString()),
				"./settings/images/Kierrosta kuvake pieni.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.EASY.toString()),
				"./settings/images/Helppo kuvake.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.NORMAL.toString()),
				"./settings/images/Tavallinen kuvake.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.HARD.toString()),
				"./settings/images/Vaikea kuvake.png"));
		this.add(difficulty);

		omitMistakesLabel = new ScalableIconLabel(dictionary.get("OMITMISTAKESLABEL_TEXT"), 
				"./settings/images/Ohita virhepainallukset.png");
		omitMistakesLabel.setHorizontalAlignment(JLabel.CENTER);
		this.add(omitMistakesLabel);
		omitMistakes = new ScalableCheckBox();
		this.add(omitMistakes);


		showScoreLabel = new ScalableIconLabel(dictionary.get("SHOWSCORELABEL_TEXT"),
				"./settings/images/Näytä pisteet.png");
		showScoreLabel.setHorizontalAlignment(JLabel.CENTER);
		this.add(showScoreLabel);
		showScore = new ScalableCheckBox();
		this.add(showScore);

		showTimeLabel = new ScalableIconLabel(dictionary.get("SHOWTIMELABEL_TEXT"),
				"./settings/images/Nayta aika kuvake.png");
		showTimeLabel.setHorizontalAlignment(JLabel.CENTER);
		this.add(showTimeLabel);
		showTime = new ScalableCheckBox();
		this.add(showTime);


		chooseCorrectAnswerImageButton = new ScalableIconButton(dictionary.get("CHOOSECORRECTANSWERIMAGEBUTTON_TEXT"),
				"./settings/images/Valitse oikein kuva kuvake.png");
		this.add(chooseCorrectAnswerImageButton);
		chooseCorrectAnswerImageButton.addActionListener(this);
		correctAnswerImagePanel = new ImagePanel();
		this.add(correctAnswerImagePanel);
		
		
		//empty row
		this.add(Box.createGlue());
		this.add(Box.createGlue());

		cancelButton = new ScalableIconButton(dictionary.get("CANCELBUTTON_TEXT"),
				"./settings/images/Takaisin.png");
		cancelButton.addActionListener(this);
		this.add(cancelButton);
		
		okButton = new ScalableIconButton(dictionary.get("OKBUTTON_TEXT"),
				"./settings/images/Hyväksy painike.png");
		okButton.setBackground(new Color(0, 127, 14));
		okButton.addActionListener(this);
		this.add(okButton);
		
	}
	
	public void setBackButtonIcon(String backbuttonImg)
	{
		if(backbuttonImg!=null && !backbuttonImg.isEmpty())
		{
			try
			{
				cancelButton.setIcon(new ImageIcon(backbuttonImg));
			}
			catch(Exception e)
			{
				System.err.println("Could not create back button icon " + backbuttonImg);
			}
		}
	}

	public void setForeground(Color color)
	{
		super.setForeground(color);
		Component[] compList = this.getComponents();
		for(int i=0;i<compList.length;i++)
		{
			compList[i].setForeground(color);
		}
	}

	public void setFont(Font font)
	{
		super.setFont(font);
		Component[] compList = this.getComponents();
		for(int i=0;i<compList.length;i++)
		{
			compList[i].setFont(font);
		}
	}

	protected SetupData getSetupData() {
		SetupData data = new SetupData();
		data.setOmitMistakes(omitMistakes.isSelected());
		data.setShowScore(showScore.isSelected());
		data.setShowTime(showTime.isSelected());
		GameDifficulty showTime = new GameDifficulty();
		String value = ((ScalableIconLabel)(this.difficulty.getSelectedItem())).getText();
		showTime.setDifficulty(dictionary.getKey(value));
		data.setGameDifficulty(showTime);

		data.setCorrectAnswerImage(correctAnswerImagePanel.getImage());
		
		return data;
	}


	public void setSetupData(SetupData setupData) {
		if(setupData==null) {
			return;
		}
		//refreshLanguage();
		if(setupData.getGameDifficulty()!=null) {
			String value = dictionary.get(setupData.getGameDifficulty().getDifficulty().toString());
			for(int i=0; i<difficulty.getItemCount(); i++)
			{
				if(difficulty.getItemAt(i).getText().equalsIgnoreCase(value))
				{
					difficulty.setSelectedItem(i);
					break;
				}
			}
		}
		omitMistakes.setSelected(setupData.isOmitMistakes());
		showScore.setSelected(setupData.isShowScore());
		showTime.setSelected(setupData.isShowTime());
		correctAnswerImagePanel.setImage(setupData.getCorrectAnswerImage());
	}


	public void addSetupEventListener(SetupEventListener listener) {
		this.listener = listener;
	}


	public void removeSetupEventListener(SetupEventListener listener) {
		if(this.listener==listener) {
			listener=null;
		}
	}
	
	private void fireSetupEvent(SetupEvent e) {
		if(listener!=null) {
			listener.setupEventOccurred(e);
		}
	}

	@Override
	public void keyPressed(KeyEvent e) {
		// none
	}

	@Override
	public void keyReleased(KeyEvent e) {
		// none
	}

	@Override
	public void keyTyped(KeyEvent e) {
		// none
	}


	public void refreshLanguage()
	{
		int choosed = -1;
		
		difficultyLabel.setText(dictionary.get("DIFFICULTYLABEL_TEXT"));
		omitMistakesLabel.setText(dictionary.get("OMITMISTAKESLABEL_TEXT"));
		showScoreLabel.setText(dictionary.get("SHOWSCORELABEL_TEXT"));
		showTimeLabel.setText(dictionary.get("SHOWTIMELABEL_TEXT"));
		okButton.setText(dictionary.get("OKBUTTON_TEXT"));
		cancelButton.setText(dictionary.get("CANCELBUTTON_TEXT"));

		chooseCorrectAnswerImageButton.setText(dictionary.get("CHOOSECORRECTANSWERIMAGEBUTTON_TEXT"));
		
		//private JComboBox showTime;
		choosed = difficulty.getSelectedIndex();
		difficulty.removeAllItems();
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.ROUNDS10.toString()),
				"./settings/images/Kierrosta kuvake pieni.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.ROUNDS20.toString()),
				"./settings/images/Kierrosta kuvake pieni.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.ROUNDS30.toString()),
				"./settings/images/Kierrosta kuvake pieni.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.EASY.toString()),
				"./settings/images/Helppo kuvake.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.NORMAL.toString()),
				"./settings/images/Tavallinen kuvake.png"));
		difficulty.addItem(new ScalableIconLabel(dictionary.get(GameDifficulty.DIFFICULTY.HARD.toString()),
				"./settings/images/Vaikea kuvake.png"));
		difficulty.setSelectedIndex(choosed);
	}
	
	protected void resizeTexts()
	{
		float fontSize = 144;
		FontMetrics fm;
		Component[] compList = this.getComponents();
		for(int i=0;i<compList.length;i++)
		{
			if(compList[i] instanceof JLabel)
			{
				JLabel lbl = (JLabel)compList[i];
				fm = lbl.getFontMetrics(lbl.getFont().deriveFont(fontSize));
				if(fm.getHeight()>lbl.getHeight())
				{
					fontSize = fontSize * lbl.getHeight() / fm.getHeight();
					fm = lbl.getFontMetrics(lbl.getFont().deriveFont(fontSize));
				}
				if(fm.stringWidth(lbl.getText())>lbl.getWidth())
				{
					fontSize = fontSize * lbl.getWidth() / fm.stringWidth(lbl.getText());
					fm = lbl.getFontMetrics(lbl.getFont().deriveFont(fontSize));
				}
			}
			else if(compList[i] instanceof JTextField)
			{
				JTextField tf = (JTextField)compList[i];
				fm = tf.getFontMetrics(tf.getFont().deriveFont(fontSize));
				if(fm.getHeight()>tf.getHeight())
				{
					fontSize = fontSize * tf.getHeight() / fm.getHeight();
					fm = tf.getFontMetrics(tf.getFont().deriveFont(fontSize));
				}
				if(fm.stringWidth(tf.getText())>tf.getWidth())
				{
					fontSize = fontSize * tf.getWidth() / fm.stringWidth(tf.getText());
					fm = tf.getFontMetrics(tf.getFont().deriveFont(fontSize));
				}
			}
			else if(compList[i] instanceof JButton)
			{
				JButton btn = (JButton)compList[i];
				fm = btn.getFontMetrics(btn.getFont().deriveFont(fontSize));
				if(fm.getHeight()>btn.getHeight())
				{
					fontSize = fontSize * btn.getHeight() / fm.getHeight();
					fm = btn.getFontMetrics(btn.getFont().deriveFont(fontSize));
				}
				if(fm.stringWidth(btn.getText())>btn.getWidth())
				{
					fontSize = fontSize * btn.getWidth() / fm.stringWidth(btn.getText());
					fm = btn.getFontMetrics(btn.getFont().deriveFont(fontSize));
				}
			}
			else if(compList[i] instanceof JComboBox)
			{
				@SuppressWarnings("unchecked")
				JComboBox<String> cb = (JComboBox<String>)compList[i];
				fm = cb.getFontMetrics(cb.getFont().deriveFont(fontSize));
				if(fm.getHeight()>cb.getHeight())
				{
					fontSize = fontSize * cb.getHeight() / fm.getHeight();
					fm = cb.getFontMetrics(cb.getFont().deriveFont(fontSize));
				}
				for(int cbi=0; i<cb.getItemCount(); cbi++)
				{
					String itemText = cb.getItemAt(cbi).toString();
					if(fm.stringWidth(itemText)>cb.getWidth())
					{
						fontSize = fontSize * cb.getWidth() / fm.stringWidth(itemText);
						fm = cb.getFontMetrics(cb.getFont().deriveFont(fontSize));
					}
				}
			}
			else if(compList[i] instanceof ScalableCheckBox)
			{
				ScalableCheckBox scb = (ScalableCheckBox)compList[i];
				fm = scb.getFontMetrics(scb.getFont().deriveFont(fontSize));
				if(fm.getHeight()>scb.getHeight())
				{
					fontSize = fontSize * scb.getHeight() / fm.getHeight();
					fm = scb.getFontMetrics(scb.getFont().deriveFont(fontSize));
				}
				if(fm.stringWidth(scb.getText())>scb.getWidth())
				{
					fontSize = fontSize * scb.getWidth() / fm.stringWidth(scb.getText());
					fm = scb.getFontMetrics(scb.getFont().deriveFont(fontSize));
				}
			}
		}
		for(int i=0;i<compList.length;i++)
		{
			compList[i].setFont(compList[i].getFont().deriveFont(fontSize));
		}
		difficultyRenderer.setMaxIconSize(difficulty.getWidth()/2, (int)(difficulty.getHeight()*0.6));
	}

	@Override
	public void actionPerformed(ActionEvent ae) {
		if(ae.getSource()==chooseCorrectAnswerImageButton)
		{
			final JFileChooser fc = new JFileChooser();
			fc.setCurrentDirectory(new File("./"));
			fc.addChoosableFileFilter(new FileFilter() {

				@Override
				public boolean accept(File f) {
				    if (f.isDirectory()) {
				        return true;
				    }

				    String filename = f.getName().toLowerCase().trim();
				    if (filename != null) {
				        if (filename.endsWith("tiff") ||
				        		filename.endsWith("tif") ||
				        		filename.endsWith("gif") ||
				        		filename.endsWith("jpeg") ||
				        		filename.endsWith("jpg") ||
				        		filename.endsWith("png")) {
				                return true;
				        } else {
				            return false;
				        }
				    }

				    return false;
				}

				@Override
				public String getDescription() {
					return null;
				}});
			fc.setAcceptAllFileFilterUsed(false);
	        int returnVal = fc.showOpenDialog(GameOptionsPanel.this);

	        if (returnVal == JFileChooser.APPROVE_OPTION) {
	            File file = fc.getSelectedFile();
	            correctAnswerImagePanel.setImage(file.getPath());
	        }
		}
		if(ae.getSource()==okButton)
		{
			SetupData setupData = getSetupData();
			fireSetupEvent(new SetupEvent(this, setupData, MESSAGE.OK));
		}
		if(ae.getSource()==cancelButton)
		{
			fireSetupEvent(new SetupEvent(this, null, MESSAGE.CANCEL));
		}
	}
}
